package com.waitingresult.demo.handler;

import cn.hutool.core.util.StrUtil;
import com.waitingresult.demo.entity.Result;
import com.waitingresult.demo.entity.ValidateVo;
import com.waitingresult.demo.enums.ErrorMessageEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.util.NestedServletException;

import javax.validation.UnexpectedTypeException;
import java.util.List;
import java.util.stream.Collectors;

import static com.waitingresult.demo.enums.ErrorMessageEnum.*;

/**
 * @Author: WangShuai
 * @CreateTime: 2023/5/18  12:43
 * @Description:
 * @Version: 1.0
 */
@Slf4j
@RestControllerAdvice
public class ExceptionHandler {
    @org.springframework.web.bind.annotation.ExceptionHandler(Exception.class)
    public Result handleException(Exception e) {
        log.error("发生异常", e);
        return Result.error("异常错误", StrUtil.isEmpty(e.getMessage()) ? ErrorMessageEnum.REQUEST_ERROR.getMsg() : e.getMessage());
    }

    @org.springframework.web.bind.annotation.ExceptionHandler(NestedServletException.class)
    public Result handleNestedServletException(NestedServletException e) {
        log.error("发生异常", e);
        return Result.error("内部服务器错误", StrUtil.isEmpty(e.getMessage()) ? ErrorMessageEnum.REQUEST_ERROR.getMsg() : e.getMessage());
    }
    @org.springframework.web.bind.annotation.ExceptionHandler(RuntimeException.class)
    public Result handleRuntimeException(RuntimeException e) {
        log.error("发生异常", e);
        return Result.error("异常错误", StrUtil.isEmpty(e.getMessage()) ? ErrorMessageEnum.REQUEST_ERROR.getMsg() : e.getMessage());
    }
    @org.springframework.web.bind.annotation.ExceptionHandler(HttpMessageNotReadableException.class)
    public Result handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        log.error("发生异常", e);
        return Result.error("异常错误", ErrorMessageEnum.HTTP_MESSAGE_NOT_READ_ERROR.getMsg());
    }
    @org.springframework.web.bind.annotation.ExceptionHandler({MethodArgumentNotValidException.class})
    public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.debug("发生异常", e);
        List<ValidateVo> validateVos = getValidateVos(e.getBindingResult());
        return Result.error(PARAMETER_PARSING_ERROR, validateVos);
    }
    @org.springframework.web.bind.annotation.ExceptionHandler({BindException.class, MethodArgumentTypeMismatchException.class, UnexpectedTypeException.class})
    public Result handleBindException(BindException e) {
        log.debug("发生异常", e);
        List<ValidateVo> validateVos = getValidateVos(e.getBindingResult());
        return Result.error(PARAMETER_PARSING_ERROR, validateVos);
    }

    @org.springframework.web.bind.annotation.ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result handleNotSupportException(HttpRequestMethodNotSupportedException e) {
        log.debug("发生异常", e);
        return Result.error("异常错误", StrUtil.isEmpty(e.getMessage()) ? ErrorMessageEnum.REQUEST_ERROR.getMsg() : e.getMessage());
    }

    /**
     * hibernate validator 异常验证VO获取
     */
    private List<ValidateVo> getValidateVos(BindingResult bindingResult) {
        return bindingResult.getFieldErrors()
                .parallelStream()
                .map(error -> new ValidateVo(error.getField(), "字段: [" + error.getField() +"],"+ error.getDefaultMessage()))
                .collect(Collectors.toList());
    }
}
